--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / backend / http / ws / handlers_lxmf.py
Displaying Raw • Download
meshchatx/src/backend/http/ws/handlers_lxmf.py master (977c7ad3) Text, 16.63 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""WebSocket handlers: handlers_lxmf."""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787httpT7ee787.T7ee787meshchat_names Tff7b72import Tb4b4b4( T8b949e# noqa: F401
Te6edf3GeoValidationErrorTb4b4b4,
Te6edf3OutboundHttpBlockedErrorTb4b4b4,
Te6edf3OverlayExportErrorTb4b4b4,
Te6edf3OverlaySourceParseErrorTb4b4b4,
Te6edf3PluginSecurityErrorTb4b4b4,
Te6edf3AsyncUtilsTb4b4b4,
Te6edf3InterfaceConfigParserTb4b4b4,
Te6edf3InterfaceDiscoveryTb4b4b4,
Te6edf3InterfaceEditorTb4b4b4,
Te6edf3LOGIN_PATHTb4b4b4,
Te6edf3LXMFTb4b4b4,
Te6edf3LxmfAudioFieldTb4b4b4,
Te6edf3LxmfFileAttachmentTb4b4b4,
Te6edf3LxmfFileAttachmentsFieldTb4b4b4,
Te6edf3LxmfImageFieldTb4b4b4,
Te6edf3MAX_EXPORT_TILESTb4b4b4,
Te6edf3MarkdownRendererTb4b4b4,
Te6edf3NomadnetFileDownloaderTb4b4b4,
Te6edf3NomadnetPageDownloaderTb4b4b4,
Te6edf3RNProbeHandlerTb4b4b4,
Te6edf3RNSTb4b4b4,
Te6edf3ReticulumMeshChatTb4b4b4,
Te6edf3SETUP_PATHTb4b4b4,
Te6edf3TRANSPARENT_TILETb4b4b4,
Te6edf3TelemeterTb4b4b4,
Te6edf3UTCTb4b4b4,
Te6edf3WSMsgTypeTb4b4b4,
Te6edf3_is_chaquopy_androidTb4b4b4,
Te6edf3_is_loopback_bind_hostTb4b4b4,
Te6edf3_request_client_ipTb4b4b4,
Te6edf3aiohttpTb4b4b4,
Te6edf3app_versionTb4b4b4,
Te6edf3assert_migration_context_pathsTb4b4b4,
Te6edf3asyncioTb4b4b4,
Te6edf3base64Tb4b4b4,
Te6edf3bcryptTb4b4b4,
Te6edf3binasciiTb4b4b4,
Te6edf3build_blocklist_export_documentTb4b4b4,
Te6edf3build_export_documentTb4b4b4,
Te6edf3build_messages_export_bundleTb4b4b4,
Te6edf3cache_statsTb4b4b4,
Te6edf3cancel_inbound_deliveriesTb4b4b4,
Te6edf3castTb4b4b4,
Te6edf3compute_lxmf_conversation_unread_from_latest_rowTb4b4b4,
Te6edf3configparserTb4b4b4,
Te6edf3contextlibTb4b4b4,
Te6edf3convert_db_favourite_to_dictTb4b4b4,
Te6edf3convert_db_lxmf_message_to_dictTb4b4b4,
Te6edf3convert_lxmf_message_to_dictTb4b4b4,
Te6edf3convert_nomadnet_field_data_to_mapTb4b4b4,
Te6edf3convert_nomadnet_string_data_to_mapTb4b4b4,
Te6edf3convert_propagation_node_state_to_stringTb4b4b4,
Te6edf3copyTb4b4b4,
Te6edf3datetimeTb4b4b4,
Te6edf3describe_port_conflictTb4b4b4,
Te6edf3detect_image_format_from_magicTb4b4b4,
Te6edf3ensure_outbound_http_allowedTb4b4b4,
Te6edf3ensure_session_csrf_tokenTb4b4b4,
Te6edf3filter_announced_dicts_by_search_queryTb4b4b4,
Te6edf3fresh_storage_at_targetTb4b4b4,
Te6edf3get_cached_active_linkTb4b4b4,
Te6edf3get_file_pathTb4b4b4,
Te6edf3get_sessionTb4b4b4,
Te6edf3get_trusted_proxy_cidrsTb4b4b4,
Te6edf3gif_utilsTb4b4b4,
Te6edf3i2p_supportTb4b4b4,
Te6edf3import_messages_export_bundleTb4b4b4,
Te6edf3ioTb4b4b4,
Te6edf3is_mbtiles_filenameTb4b4b4,
Te6edf3is_path_within_dirTb4b4b4,
Te6edf3is_port_in_useTb4b4b4,
Te6edf3is_user_facing_lxmf_payloadTb4b4b4,
Te6edf3jsonTb4b4b4,
Te6edf3list_host_network_interfacesTb4b4b4,
Te6edf3list_inbound_deliveriesTb4b4b4,
Te6edf3list_portsTb4b4b4,
Te6edf3load_app_security_settingsTb4b4b4,
Te6edf3loggerTb4b4b4,
Te6edf3loggingTb4b4b4,
Te6edf3lxmf_sidebar_preview_for_conversation_latest_rowTb4b4b4,
Te6edf3memory_log_handlerTb4b4b4,
Te6edf3message_fields_have_attachmentsTb4b4b4,
Te6edf3migrate_legacy_to_targetTb4b4b4,
Te6edf3mime_for_image_typeTb4b4b4,
Te6edf3normalize_identity_storage_hashTb4b4b4,
Te6edf3normalize_lxmf_sieve_filtersTb4b4b4,
Te6edf3normalize_message_blocklistTb4b4b4,
Te6edf3osTb4b4b4,
Te6edf3parse_bool_query_paramTb4b4b4,
Te6edf3parse_import_documentTb4b4b4,
Te6edf3parse_lxmf_display_nameTb4b4b4,
Te6edf3parse_lxmf_propagation_node_app_dataTb4b4b4,
Te6edf3parse_lxmf_sieve_filters_jsonTb4b4b4,
Te6edf3parse_lxmf_stamp_costTb4b4b4,
Te6edf3parse_message_blocklist_jsonTb4b4b4,
Te6edf3parse_nomadnetwork_node_display_nameTb4b4b4,
Te6edf3platformTb4b4b4,
Te6edf3privacy_mode_enabledTb4b4b4,
Te6edf3psutilTb4b4b4,
Te6edf3purge_messages_before_cutoffTb4b4b4,
Te6edf3reTb4b4b4,
Te6edf3resolve_message_age_cutoffTb4b4b4,
Te6edf3reticulum_pathfindingTb4b4b4,
Te6edf3rotate_session_csrf_tokenTb4b4b4,
Te6edf3rrc_protocolTb4b4b4,
Te6edf3safe_path_under_dirTb4b4b4,
Te6edf3sanitize_sticker_emojiTb4b4b4,
Te6edf3sanitize_sticker_nameTb4b4b4,
Te6edf3sanitize_websocket_config_updateTb4b4b4,
Te6edf3save_app_security_settingsTb4b4b4,
Te6edf3secretsTb4b4b4,
Te6edf3shutilTb4b4b4,
Te6edf3sqlite3Tb4b4b4,
Te6edf3sticker_pack_utilsTb4b4b4,
Te6edf3sysTb4b4b4,
Te6edf3tempfileTb4b4b4,
Te6edf3threadingTb4b4b4,
Te6edf3timeTb4b4b4,
Te6edf3tracebackTb4b4b4,
Te6edf3user_agent_hashTb4b4b4,
Te6edf3validate_export_documentTb4b4b4,
Te6edf3webTb4b4b4,
Te6edf3websocket_type_requires_authTb4b4b4,
Te6edf3zipfileTb4b4b4,
Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ffhandle_lxmf_forwarding_rules_getTb4b4b4(Te6edf3appTb4b4b4, Te6edf3clientTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3rules Tff7b72= Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffmiscTff7b72.Td2a8ffget_forwarding_rulesTb4b4b4(Tb4b4b4)
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxmf.forwarding.rulesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrulesTa5d6ff"Tb4b4b4: Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3ruleTb4b4b4[Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3ruleTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffidentity_hashTa5d6ff"Tb4b4b4: Te6edf3ruleTb4b4b4[Ta5d6ff"Ta5d6ffidentity_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffforward_to_hashTa5d6ff"Tb4b4b4: Te6edf3ruleTb4b4b4[Ta5d6ff"Ta5d6ffforward_to_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffsource_filter_hashTa5d6ff"Tb4b4b4: Te6edf3ruleTb4b4b4[Ta5d6ff"Ta5d6ffsource_filter_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffis_activeTa5d6ff"Tb4b4b4: Tffa657boolTb4b4b4(Te6edf3ruleTb4b4b4[Ta5d6ff"Ta5d6ffis_activeTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72for Te6edf3rule Tff7b72in Te6edf3rules
Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ffhandle_lxmf_forwarding_rule_addTb4b4b4(Te6edf3appTb4b4b4, Te6edf3clientTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3rule_data Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffruleTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3rule_data Tff7b72or Ta5d6ff"Ta5d6ffforward_to_hashTa5d6ff" Tff7b72not Tff7b72in Te6edf3rule_dataTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6ff"Ta5d6ffMissing rule data or forward_to_hash in lxmf.forwarding.rule.addTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72return
Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffmiscTff7b72.Td2a8ffcreate_forwarding_ruleTb4b4b4(
Te6edf3identity_hashTff7b72=Te6edf3rule_dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidentity_hashTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3forward_to_hashTff7b72=Te6edf3rule_dataTb4b4b4[Ta5d6ff"Ta5d6ffforward_to_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3source_filter_hashTff7b72=Te6edf3rule_dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsource_filter_hashTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3is_activeTff7b72=Te6edf3rule_dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_activeTa5d6ff"Tb4b4b4, Tff7b72TrueTb4b4b4)Tb4b4b4,
Te6edf3nameTff7b72=Te6edf3rule_dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e# notify updated
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3appTff7b72.Td2a8ffon_websocket_data_receivedTb4b4b4(
Te6edf3clientTb4b4b4,
Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxmf.forwarding.rules.getTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ffhandle_lxmf_forwarding_rule_deleteTb4b4b4(Te6edf3appTb4b4b4, Te6edf3clientTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3rule_id Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3rule_id Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffmiscTff7b72.Td2a8ffdelete_forwarding_ruleTb4b4b4(Te6edf3rule_idTb4b4b4)
T8b949e# notify updated
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3appTff7b72.Td2a8ffon_websocket_data_receivedTb4b4b4(
Te6edf3clientTb4b4b4,
Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxmf.forwarding.rules.getTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ffhandle_lxmf_forwarding_rule_toggleTb4b4b4(Te6edf3appTb4b4b4, Te6edf3clientTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3rule_id Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3rule_id Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffmiscTff7b72.Td2a8fftoggle_forwarding_ruleTb4b4b4(Te6edf3rule_idTb4b4b4)
T8b949e# notify updated
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3appTff7b72.Td2a8ffon_websocket_data_receivedTb4b4b4(
Te6edf3clientTb4b4b4,
Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxmf.forwarding.rules.getTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e# handle ingesting an lxmf uri (paper message)
Tff7b72async Tff7b72def Td2a8ffhandle_lxm_ingest_uriTb4b4b4(Te6edf3appTb4b4b4, Te6edf3clientTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3uri Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffuriTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3uriTb4b4b4:
Tff7b72return
Te6edf3local_delivery_signal Tff7b72= Ta5d6ff"Ta5d6fflocal_delivery_occurredTa5d6ff"
Te6edf3duplicate_signal Tff7b72= Ta5d6ff"Ta5d6ffduplicate_lxmTa5d6ff"
Tff7b72tryTb4b4b4:
Te6edf3uri_raw Tff7b72= Te6edf3uriTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3lu Tff7b72= Te6edf3uri_rawTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3luTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx://mapTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3luTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffmeshchat://mapTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72from T7ee787urllibT7ee787.T7ee787parse Tff7b72import Te6edf3parse_qslTb4b4b4, Te6edf3urlparse
Te6edf3parsed Tff7b72= Te6edf3urlparseTb4b4b4(Te6edf3uri_rawTb4b4b4)
Te6edf3q Tff7b72= Tffa657dictTb4b4b4(Te6edf3parse_qslTb4b4b4(Te6edf3parsedTff7b72.Td2a8ffqueryTb4b4b4, Te6edf3keep_blank_valuesTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3lat Tff7b72= Tffa657floatTb4b4b4(Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflatTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)
Te6edf3lon Tff7b72= Tffa657floatTb4b4b4(Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffInvalid map link: lat and lon must be numbers.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return
Te6edf3zraw Tff7b72= Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffzTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffzoomTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff10Ta5d6ff"
Tff7b72tryTb4b4b4:
Te6edf3zoom Tff7b72= Tffa657intTb4b4b4(Tffa657floatTb4b4b4(Te6edf3zrawTb4b4b4)Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Te6edf3zoom Tff7b72= T79c0ff10
Te6edf3zoom Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff22Tb4b4b4, Te6edf3zoomTb4b4b4)Tb4b4b4)
Te6edf3layers Tff7b72= Tb4b4b4(Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflayersTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3label Tff7b72= Tb4b4b4(Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflabelTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3mq Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6fflatTa5d6ff"Tb4b4b4: Te6edf3latTb4b4b4,
Ta5d6ff"Ta5d6fflonTa5d6ff"Tb4b4b4: Te6edf3lonTb4b4b4,
Ta5d6ff"Ta5d6ffzoomTa5d6ff"Tb4b4b4: Te6edf3zoomTb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3layersTb4b4b4:
Te6edf3mqTb4b4b4[Ta5d6ff"Ta5d6fflayersTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3layers
Tff7b72if Te6edf3labelTb4b4b4:
Te6edf3mqTb4b4b4[Ta5d6ff"Ta5d6fflabelTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3label
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffOpening map view.Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffingest_typeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmap_viewTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmap_queryTa5d6ff"Tb4b4b4: Te6edf3mqTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return
Tff7b72if Te6edf3uri_rawTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstartswithTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx://Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmeshchat://Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72from T7ee787urllibT7ee787.T7ee787parse Tff7b72import Te6edf3parse_qslTb4b4b4, Te6edf3unquoteTb4b4b4, Te6edf3urlparse
Te6edf3_parsed Tff7b72= Te6edf3urlparseTb4b4b4(Te6edf3uri_rawTb4b4b4)
Te6edf3_sch Tff7b72= Tb4b4b4(Te6edf3_parsedTff7b72.Td2a8ffscheme Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3_host Tff7b72= Tb4b4b4(Te6edf3_parsedTff7b72.Td2a8ffnetloc Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3_sch Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffmeshchatxTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmeshchatTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3_host Tff7b72== Ta5d6ff"Ta5d6ffdocsTa5d6ff"Tb4b4b4:
Te6edf3_q Tff7b72= Tffa657dictTb4b4b4(Te6edf3parse_qslTb4b4b4(Te6edf3_parsedTff7b72.Td2a8ffqueryTb4b4b4, Te6edf3keep_blank_valuesTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4)
Te6edf3rel Tff7b72= Tb4b4b4(Te6edf3_qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreticulumTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3_qTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3rel Tff7b72and Te6edf3_parsedTff7b72.Td2a8ffpath Tff7b72and Te6edf3_parsedTff7b72.Td2a8ffpath Tff7b72!= Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4:
Te6edf3rel Tff7b72= Te6edf3unquoteTb4b4b4(Te6edf3_parsedTff7b72.Td2a8ffpathTff7b72.Td2a8fflstripTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3payloadTb4b4b4: Tffa657dict Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffOpening documentation.Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffingest_typeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffdocs_viewTa5d6ff"Tb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3relTb4b4b4:
Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffdocs_queryTa5d6ff"Tb4b4b4] Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffreticulumTa5d6ff"Tb4b4b4: Te6edf3relTb4b4b4}
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return
T8b949e# Known hosts (map/docs) are handled above. Relay and app
T8b949e# deep links are frontend-routed. Anything else must not
T8b949e# fall through to LXMF ingest.
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Tb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffUnknown or unsupported meshchatx link host Ta5d6ff"
Ta5d6fffTa5d6ff"Ta5d6ff'Tffd700{Te6edf3_host Tff7b72or Ta5d6ff'Ta5d6ff(empty)Ta5d6ff'Tffd700}Ta5d6ff'Ta5d6ff. Ta5d6ff"
Ta5d6ff"Ta5d6ffSupported hosts include map, docs, relay, and app.Ta5d6ff"
Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffingest_typeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffunknown_meshchatxTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhostTa5d6ff"Tb4b4b4: Te6edf3_hostTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return
T8b949e# LXMA contact sharing URI:
T8b949e# lxma://<destination_hash_hex>:<public_key_hex>
Tff7b72if Te6edf3uri_rawTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6fflxma://Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787lxma_contact Tff7b72import Te6edf3bind_lxma_contact
Te6edf3destination_hash_hexTb4b4b4, Te6edf3identity Tff7b72= Te6edf3bind_lxma_contactTb4b4b4(
Te6edf3uri_rawTb4b4b4,
Te6edf3appTff7b72.Td2a8ff_identity_from_public_key_bytesTb4b4b4,
Tb4b4b4)
Te6edf3remote_identity_hash Tff7b72= Te6edf3identityTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Te6edf3existing_contact Tff7b72= Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffcontactsTff7b72.Td2a8ffget_contact_by_identity_hashTb4b4b4(
Te6edf3remote_identity_hashTb4b4b4,
Tb4b4b4)
Te6edf3contact_name Tff7b72= Tb4b4b4(
Te6edf3existing_contactTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]
Tff7b72if Te6edf3existing_contact Tff7b72and Te6edf3existing_contactTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)
Tff7b72else Ta5d6fffTa5d6ff"Ta5d6ffContact Tffd700{Te6edf3destination_hash_hexTb4b4b4[Tb4b4b4:T79c0ff8Tb4b4b4]Tffd700}Ta5d6ff"
Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffcontactsTff7b72.Td2a8ffadd_contactTb4b4b4(
Te6edf3contact_nameTb4b4b4,
Te6edf3remote_identity_hashTb4b4b4,
Te6edf3lxmf_addressTff7b72=Te6edf3destination_hash_hexTb4b4b4,
Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffsync_telephone_call_policyTb4b4b4(Tb4b4b4)
T8b949e# Persist pubkey so outbound LXMF works before any announce.
Tff7b72tryTb4b4b4:
Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffrememberTb4b4b4(
Tff7b72NoneTb4b4b4,
Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3destination_hash_hexTb4b4b4)Tb4b4b4,
Te6edf3identityTff7b72.Td2a8ffget_public_keyTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72NoneTb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3remember_excTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffLXMA remember failed for Tffd700{Te6edf3destination_hash_hexTffd700}Ta5d6ff: Ta5d6ff"
Ta5d6fffTa5d6ff"Tffd700{Tffa657typeTb4b4b4(Te6edf3remember_excTb4b4b4)Tff7b72.Td2a8ff__name__Tffd700}Ta5d6ff: Tffd700{Te6edf3remember_excTffd700!r}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ffContact imported from LXMA URI (Tffd700{Te6edf3destination_hash_hexTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffingest_typeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxma_contactTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Te6edf3destination_hash_hexTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return
T8b949e# ensure uri starts with lxmf:// or lxm://
Tff7b72if Tff7b72not Te6edf3uriTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstartswithTb4b4b4(
Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffURI_SCHEMA Tff7b72+ Ta5d6ff"Ta5d6ff://Ta5d6ff"Tb4b4b4,
Tb4b4b4) Tff7b72and Tff7b72not Te6edf3uriTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6fflxm://Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ff:Ta5d6ff" Tff7b72in Te6edf3uri Tff7b72and Ta5d6ff"Ta5d6ff//Ta5d6ff" Tff7b72not Tff7b72in Te6edf3uriTb4b4b4:
Te6edf3uri Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffURI_SCHEMA Tff7b72+ Ta5d6ff"Ta5d6ff://Ta5d6ff" Tff7b72+ Te6edf3uri
Tff7b72elseTb4b4b4:
Te6edf3uri Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffURI_SCHEMA Tff7b72+ Ta5d6ff"Ta5d6ff://Ta5d6ff" Tff7b72+ Te6edf3uri
Te6edf3ingest_result Tff7b72= Te6edf3appTff7b72.Td2a8ffmessage_routerTff7b72.Td2a8ffingest_lxm_uriTb4b4b4(
Te6edf3uriTb4b4b4,
Te6edf3signal_local_deliveryTff7b72=Te6edf3local_delivery_signalTb4b4b4,
Te6edf3signal_duplicateTff7b72=Te6edf3duplicate_signalTb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3ingest_result Tff7b72is Tff7b72FalseTb4b4b4:
Te6edf3response Tff7b72= Ta5d6ff"Ta5d6ffThe URI contained no decodable messagesTa5d6ff"
Te6edf3status Tff7b72= Ta5d6ff"Ta5d6fferrorTa5d6ff"
Tff7b72elif Te6edf3ingest_result Tff7b72== Te6edf3local_delivery_signalTb4b4b4:
Te6edf3response Tff7b72= Ta5d6ff"Ta5d6ffMessage was decoded, decrypted successfully, and added to your conversation list.Ta5d6ff"
Te6edf3status Tff7b72= Ta5d6ff"Ta5d6ffsuccessTa5d6ff"
Tff7b72elif Te6edf3ingest_result Tff7b72== Te6edf3duplicate_signalTb4b4b4:
Te6edf3response Tff7b72= Ta5d6ff"Ta5d6ffThe decoded message has already been processed by the LXMF Router, and will not be ingested again.Ta5d6ff"
Te6edf3status Tff7b72= Ta5d6ff"Ta5d6ffinfoTa5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3response Tff7b72= Ta5d6ff"Ta5d6ffThe decoded message was not addressed to your LXMF address, and has been discarded.Ta5d6ff"
Te6edf3status Tff7b72= Ta5d6ff"Ta5d6ffwarningTa5d6ff"
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Te6edf3statusTb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Te6edf3responseTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.ingest_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ffError ingesting message from URI: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e# handle generating a paper message uri
Tff7b72async Tff7b72def Td2a8ffhandle_lxm_generate_paper_uriTb4b4b4(Te6edf3appTb4b4b4, Te6edf3clientTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3destination_hash Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4)
Te6edf3content Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4)
Te6edf3title Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3destination_hash Tff7b72or Tff7b72not Te6edf3contentTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3destination_hash_bytes Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3destination_hashTb4b4b4)
Te6edf3destination_identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffrecallTb4b4b4(Te6edf3destination_hash_bytesTb4b4b4)
Tff7b72if Te6edf3destination_identity Tff7b72is Tff7b72NoneTb4b4b4:
T8b949e# try to find in database
Te6edf3announce Tff7b72= Te6edf3appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffannouncesTff7b72.Td2a8ffget_announce_by_hashTb4b4b4(
Te6edf3destination_hashTb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3announce Tff7b72and Te6edf3announceTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidentity_public_keyTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3destination_identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffrom_bytesTb4b4b4(
Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Te6edf3announceTb4b4b4[Ta5d6ff"Ta5d6ffidentity_public_keyTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3destination_identity Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ExceptionTb4b4b4(
Ta5d6ff"Ta5d6ffRecipient identity not found. Please wait for an announce or add them as a contact.Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3lxmf_destination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(
Te6edf3destination_identityTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffOUTTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLETb4b4b4,
Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdeliveryTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3lxm Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4(
Te6edf3lxmf_destinationTb4b4b4,
Te6edf3appTff7b72.Td2a8fflocal_lxmf_destinationTb4b4b4,
Te6edf3contentTb4b4b4,
Te6edf3titleTff7b72=Te6edf3titleTb4b4b4,
Te6edf3desired_methodTff7b72=Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffPAPERTb4b4b4,
Tb4b4b4)
T8b949e# generate uri
Te6edf3uri Tff7b72= Te6edf3lxmTff7b72.Td2a8ffas_uriTb4b4b4(Tb4b4b4)
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.generate_paper_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffuriTa5d6ff"Tb4b4b4: Te6edf3uriTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflxm.generate_paper_uri.resultTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ffError generating paper message: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e# handle getting keyboard shortcuts
Te6edf3HANDLERS Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6fflxmf.forwarding.rules.getTa5d6ff"Tb4b4b4: Te6edf3handle_lxmf_forwarding_rules_getTb4b4b4,
Ta5d6ff"Ta5d6fflxmf.forwarding.rule.addTa5d6ff"Tb4b4b4: Te6edf3handle_lxmf_forwarding_rule_addTb4b4b4,
Ta5d6ff"Ta5d6fflxmf.forwarding.rule.deleteTa5d6ff"Tb4b4b4: Te6edf3handle_lxmf_forwarding_rule_deleteTb4b4b4,
Ta5d6ff"Ta5d6fflxmf.forwarding.rule.toggleTa5d6ff"Tb4b4b4: Te6edf3handle_lxmf_forwarding_rule_toggleTb4b4b4,
Ta5d6ff"Ta5d6fflxm.ingest_uriTa5d6ff"Tb4b4b4: Te6edf3handle_lxm_ingest_uriTb4b4b4,
Ta5d6ff"Ta5d6fflxm.generate_paper_uriTa5d6ff"Tb4b4b4: Te6edf3handle_lxm_generate_paper_uriTb4b4b4,
Tb4b4b4}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────